package com.itmuch.box.controller.common;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.google.common.collect.Lists;
import com.itmuch.box.core.base.BaseController;
import com.itmuch.box.core.constant.ConstantCode;
import com.itmuch.box.core.constant.ConstantConfig;
import com.itmuch.box.core.converter.AjaxResult;
import com.itmuch.box.core.exception.BusinessException;
import com.itmuch.box.core.security.SubjectUtil;
import com.itmuch.box.domain.attach.entity.Attach;
import com.itmuch.box.service.attach.AttachService;
import com.itmuch.box.service.config.ConfigService;
import com.itmuch.box.util.ErrorMsgUtil;

@Controller
@RequestMapping(value = "${commonPath}/upload")
public class FileUploadController extends BaseController {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadController.class);
    @Value("${uploadPath}")
    protected String uploadPath;

    @Resource
    private ConfigService configService;
    @Resource
    private AttachService attachService;

    /**
     * 上传文件, 并返回附件id
     * @param request 请求
     * @param file 文件
     * @return 返回路径
     * @throws Exception
     */
    @RequestMapping(value = "/upload-ret-ids", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult upload4Id(HttpServletRequest request, @RequestParam(value = "file", required = true) MultipartFile[] files)
            throws BusinessException {
        try {
            if (files != null && files.length > 0) {
                List<Integer> ids = Lists.newArrayList();
                for (MultipartFile file : files) {
                    Attach attach = this.uploadFile(request, file);
                    Integer id = attach.getId();
                    ids.add(id);
                }

                return new AjaxResult(ids);
            }
            return ErrorMsgUtil.error("文件为空", "文件为空", ConstantCode.PARAMTER_ERROR_CODE);

        } catch (Exception e) {
            LOGGER.warn("写文件发生异常,{}", e);
            throw new BusinessException("写文件发生异常");
        }
    }

    // TODO 视频和图片等的文件大小限制不同, 需要写一下.
    @RequestMapping(value = "/upload-ret-url", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult upload4Url(HttpServletRequest request, @RequestParam(value = "file", required = true) MultipartFile file)
            throws BusinessException {
        return this.upload4URL(request, file);
    }

    // TODO 视频和图片等的文件大小限制不同, 需要写一下.
    @RequestMapping(value = "/upload-cover-ret-url", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult uploadCover4Url(HttpServletRequest request, @RequestParam(value = "coverFile", required = true) MultipartFile file)
            throws BusinessException {
        return this.upload4URL(request, file);
    }

    // TODO 视频和图片等的文件大小限制不同, 需要写一下.
    @RequestMapping(value = "/upload-video-ret-url", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult uploadVideo4Url(HttpServletRequest request, @RequestParam(value = "videoFile", required = true) MultipartFile file)
            throws BusinessException {
        return this.upload4URL(request, file);
    }

    public AjaxResult upload4URL(HttpServletRequest request, @RequestParam(value = "file", required = true) MultipartFile file)
            throws BusinessException {
        try {
            Attach attach = this.uploadFile(request, file);
            String attachDomain = this.configService.selectValueByKey(ConstantConfig.ATTACH_DOMAIN);
            String url = String.format("%s/%s", attachDomain, attach.getPath());
            return new AjaxResult(url);
        } catch (Exception e) {
            LOGGER.warn("写文件发生异常,{}", e);
            throw new BusinessException("写文件发生异常");
        }
    }

    private Attach uploadFile(HttpServletRequest request, MultipartFile file) throws IOException {
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        Integer memberId = SubjectUtil.getSubjectId();
        String originalFilename = file.getOriginalFilename();
        String extension = FilenameUtils.getExtension(originalFilename);

        // 保存的文件名 UUID.后缀
        String uuid = UUID.randomUUID().toString();
        String savedFilename = uuid + "." + extension;

        // 相对于attach.domain的路径
        String dirInAttachDomain = String.format("%s/%s/%s/%s", this.uploadPath, this.projectCode, memberId, dateStr);
        // 相对attach.domain的url
        String urlInAttachDomain = String.format("%s/%s", dirInAttachDomain, savedFilename);

        // 文件所在目录在磁盘里的全路径
        String dirInDisk = String.format("%s/%s", this.attachLocation, dirInAttachDomain);
        File dirPath = new File(dirInDisk);
        if (!dirPath.exists()) {
            dirPath.mkdirs();
        }

        // 文件在磁盘中的全路径
        File fileToWrite = new File(String.format("%s/%s", dirInDisk, savedFilename));

        byte[] bytes = file.getBytes();
        FileCopyUtils.copy(bytes, fileToWrite);

        Attach attach = new Attach();
        attach.setMemberId(memberId);
        attach.setOriginalFilename(originalFilename);
        attach.setPath(urlInAttachDomain);
        attach.setUuid(uuid);

        this.attachService.insert(attach);
        return attach;
    }
}
